package parallels.servertech.server;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;

import parallels.servertech.common.Status;

public class ConnectionHandler implements Runnable {
	private static final Logger log = Logger.getLogger("handler");
	private static final int SOCKET_TIMEOUT = 1000;
	
	private final Receiver receiver;
	private final Socket socket;
	private final DataInputStream input;
	private final DataOutputStream output;
	
	private boolean done = false;
	
	public ConnectionHandler(Receiver receiver, Socket socket) throws IOException {
		this.receiver = receiver;
		this.socket = socket;
		this.socket.setSoTimeout(SOCKET_TIMEOUT);
		input = new DataInputStream(socket.getInputStream());
		output = new DataOutputStream(socket.getOutputStream());
	}

	@Override
	public void run() {
		while (!done) {
			try {
				done = handle();
			} catch (SocketTimeoutException timeoutEx) {
				log.fine("client socket timeout");
				if (Thread.interrupted()) {
					log.info("client connection handler stopped");
					return;
				}
			} catch (EOFException eof) {
				log.info("client connection closed");
				try {
					socket.close();
					log.info("server connection closed");
					return;
				} catch (IOException closeEx) {
					log.warning("failed to close socket");
				}
			} catch (IOException ioe) {
				log.info("error: " + ioe.getClass().getName() + "(" + ioe.getMessage() + ")");
				log.log(Level.SEVERE, "error: ", ioe);
			}
		}
	}
	
	private boolean handle() throws IOException {
		log.fine("waiting for client command");
		String command = input.readUTF();
		log.info(command + " command received");
		if ("add".equals(command)) {
			int left = input.readInt();
			int right = input.readInt();
			log.info("adding to numbers: " + left + " + " + right);
			output.writeInt(Status.SUCCESS.ordinal());
			output.writeInt(left + right);
		} else if ("shutdown".equals(command)) {
			output.writeInt(Status.SUCCESS.ordinal());
			receiver.stop();
			return true;
		} else {
			output.writeInt(Status.FAILURE.ordinal());
			output.writeUTF("unknown command");
		}
		
		return false;
	}
}
